Johan Sundberg, the Content Studio Development team

Content Studio 5.2
In Content Studio 5.2 this functionality is no longer necessary. You can accomplish the same thing by using the new VirtualPath property on any unit, category or document in Content Studio.

URL rewriting is a technique to change or rewrite the URL before the web server executes it. The main reason for URL rewriting is to make URL's more user friendly and easier to read. This article explains a little how it works, how it is configured and a real life example of how it could be used.

Background

The rewrite engine is a .NET Http module that must be installed on the server. The engine is then hooked in before any other .NET page is executed.

The order of which are executed:

  1. The IIS checks the URL against "regular" files such as .txt, .jpg and .html. If one is found it is returned to the client.
  2. Next application extensions are checked - aspx, asp etc. These are defined in the IIS. If it is a .NET application the rewrite engine will act first, see next number.
  3. Now .NET is activated, and first the rewrite engine has the control. It checks the URL against rule(s) and if a match occurs, it rewrites the URL.
  4. The rest of .NET - aspx, asmx etc.

Installation

  1. The rewrite engine comes as dll which must be installed on the site.
  2. Open Content Studio admin, navigate to System\Assemblies. Right click and choose new document. Find the file URLRewriter.dll and upload it.

    uploading dll to content studio
  3. Open the site's web.config (Located in [Content Studio installation directory]/Websites/[site]). 
  4. Add the following directly after <configuration>:
     
    Xml
    <configSections>
      <section name="RewriterConfig" 
                  type="URLRewriter.Config.RewriterConfigSerializerSectionHandler, URLRewriter" />
    </configSections>
    
  5. Add the following to <system.web>:
     
    Xml
    <httpModules>  
      <add type="URLRewriter.ModuleRewriter, URLRewriter" name="ModuleRewriter" />
    </httpModules>
    
  6. Add the following after <system.web>:

    Xml
    <RewriterConfig>
      <Rules> 
        <RewriterRule>      
          <LookFor>~/([\d]+)$</LookFor>      
          <SendTo>~/default.aspx?di=$1</SendTo>    
        </RewriterRule>  
      </Rules>
    </RewriterConfig>
  7. Open web.config for admin  (Located [Content Studio installation directory]/Admin).
  8. Add the following to <system.web>:
     
    Xml
    <httpModules>
      <remove name="ModuleRewriter"/> 
    </httpModules>
  9. Navigate to Control Panel/Administration tools/.
    Open Internet Information Services (IIS6) Manager.
  10. Open site properties (or virutal directory properties), click tab Home directory (Virtual directory) and press the Configuration button. Under Wildcard application maps press insert and type %WINDIR%\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll (for 64-bit servers this would be %WINDIR%\microsoft.net\framework64\v2.0.50727\aspnet_isapi.dll) Make sure "Verify that file exists" is unchecked. Press OK. Just press OK when a dialog asking about inheritance popup.

    application extensions mappings

Configuration

Configuring rewriter rules can be a little tricky - it requires knowledge in regular expressions. In the previous section under step 6, a sample rewrite rule was installed. Every rewrite rule consists of a xml node RewriteRule with two children LookFor and SendTo. How it works should be pretty straight forward. The LookFor regular expression is tested against incoming URL's and if there is a match the URL will be replaced with SendTo. The rewrite engine checks the rules one by one starting at the first and a will quit when it hits.

With the sample rule installed the URL http://www.company.com/1000 is sent to http://www.company.com/default.aspx?di=1000.

~/ matches the site root directory.
\d is any number.
([\d]+) is one or more of any number, and also captures the match meaning it can be read in $1..$9
$ denotes end of line
$1 in SendTo is replaced with whatever matches ([\d]+) - which is one or more of any numbers.

Example

This company wants their contact page and news page to be accessible through a nice URL. They also want the news page to only show news from a certain year if a year is passed after /news. Supported URL are:

http://www.company.com/contact
http://www.company.com/news
http://www.company.com/news/2007

These requirements are met through these rules:

 
Xml
<!-- /contact or /contact/ leads to document with id 1234 -->
<RewriterRule>
  <LookFor>~/contact[/]?$</LookFor>
  <SendTo>~/default.aspx?di=1234</SendTo>
</RewriterRule>

<!-- other contact urls are sent to the root -->
<RewriterRule>
  <LookFor>~/contact/(.+)$</LookFor>
  <SendTo>~/$1</SendTo>
</RewriterRule>
    
<!-- /news/ followed by a number is sent to 1122 with year querystring -->
<RewriterRule>
  <LookFor>~/news/([\d]+)$</LookFor>
  <SendTo>~/default.aspx?di=1122&amp;year=$1</SendTo>
</RewriterRule>

<!-- /news or /news/ is sent to 1122 -->
<RewriterRule>
  <LookFor>~/news[/]?$</LookFor>
  <SendTo>~/default.aspx?di=1122</SendTo>
</RewriterRule>

<!-- other news urls are sent to the root -->
<RewriterRule>
  <LookFor>~/news/(.+)$</LookFor>
  <SendTo>~/$1</SendTo>
</RewriterRule>

Rule two and five are a little special and requires more explanation. Let's say http://www.company.com/news/ is requested. This URL is sent to http://www.company.com/default.aspx?di=1122 but the browser will still think it is in the news directory and therefore all relatives URL will be relative to news. Relative links such as default.aspx?di=1234 will link to news/default.aspx?di=1234, the script ~js/global.js is assumed to be in news also. Rule two and five are work a rounds to this problem. Rule five for example states that anything following /news/ is sent to the application root  (http://www.company.com/).

There is another problem. Relative URL's are generated by Content Studio AS components such as Insert Menu 3.0. To overcome the problem with links pointing to wrong location there is a html element that can be added to the page header:

The base tag is used to set the base URL that relative URL's omits from.
Html
<base href="http://www.company.com" />

Add this code to code behind on a page and by doing that relative URL's will always start with the right URL.

This code creates the base tag, adds href attribute and finally adds the control to the header.
C#
HtmlGenericControl control = new HtmlGenericControl("base"); 
control.Attributes.Add("href", Application["CS_SiteURL"].ToString()); 
Page.Header.Controls.AddAt(0, control);
VB.NET
Dim control As New HtmlGenericControl("base")
control.Attributes.Add("href", Application("CS_SiteURL").ToString())
Page.Header.Controls.AddAt(0, control)